package org.ioriframework.boot.job.service;

import java.util.List;

import org.ioriframework.boot.core.annotation.PermissionOperation;
import org.ioriframework.boot.core.annotation.PermissionResource;
import org.ioriframework.boot.core.annotation.PermissionUrlBound;
import org.ioriframework.boot.core.base.vo.PageVO;
import org.ioriframework.boot.job.dao.IJobDao;
import org.ioriframework.boot.job.trigger.JobTrigger;
import org.ioriframework.boot.job.vo.JobVO;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value="job")
@PermissionResource(code = "job", desc = "iori.resource.jobService")
public class JobService {
	
	private static Logger log = LoggerFactory.getLogger(JobService.class);
	
	@Autowired
	private IJobDao jobDao;
	
	@Autowired
	private JobTrigger jobTrigger;

	/**
	 * 查询JOB列表
	 * @param jobVO
	 * @param pageVO
	 * @return
	 */
	@PermissionOperation(code=PermissionOperation.SEARCH, desc="iori.operation.findJob", urls = {
			@PermissionUrlBound(url = "ioriframework/boot/job/jobList.html") })
	@GetMapping(value="/list", produces = "application/json; charset=UTF-8")
	public PageVO<JobVO> findJobList(JobVO jobVO, PageVO<JobVO> pageVO) {
		log.info("findJobList start...");
		pageVO = jobDao.findJobList(jobVO, pageVO);
		return pageVO;
	}
	

	/**
	 * 通过ID查询Job
	 * @param jobId
	 * @return
	 */
	@PermissionOperation(code=PermissionOperation.SEARCH, desc="iori.operation.findJob")
	@GetMapping(value="find/{jobId}", produces = "application/json; charset=UTF-8")
	public JobVO findJobById(@PathVariable("jobId")Integer jobId) {
		return jobDao.findJobById(jobId);
	}

	/**
	 * 创建Job
	 * @param jobVO
	 * @throws SchedulerException 
	 */
	@PermissionOperation(code=PermissionOperation.CREATE, desc="iori.operation.createJob")
	@Transactional(transactionManager="txManager")
	@PostMapping(value="create", produces = "application/json; charset=UTF-8")
	public int createJob(@RequestBody JobVO jobVO) throws SchedulerException {
		JobVO vo = jobDao.findJob(jobVO);
		if(vo != null) {
			return -1;
		} else {
			// 更新任务时，默认状态为运行中
			jobVO.setStatus(1);
			jobDao.createJob(jobVO);
			jobTrigger.scheduleJob(jobVO);
		}
		return 1;
	}
	
	/**
	 * 批量创建Job
	 * @param jobVOs
	 * @return
	 * @throws SchedulerException
	 */
	@PermissionOperation(code=PermissionOperation.CREATE, desc="iori.operation.createJob")
	@Transactional(transactionManager="txManager")
	@PostMapping(value="createJobs", produces = "application/json; charset=UTF-8")
	public List<JobVO> createJobs(@RequestBody List<JobVO> jobVOs) throws SchedulerException {
		for(JobVO jobVO : jobVOs) {
			try {
				createJob(jobVO);
			} catch(SchedulerException e) {}
		}
		return jobVOs;
	}
	
	/**
	 * 删除Job
	 * @param jobId
	 * @throws SchedulerException 
	 */
	@PermissionOperation(code=PermissionOperation.DELETE, desc="iori.operation.deleteJob")
	@Transactional(transactionManager="txManager")
	@DeleteMapping(value="delete/{JobId}", produces = "application/json; charset=UTF-8")
	public void deleteJob(@PathVariable("JobId")Integer jobId) throws SchedulerException {
		JobVO jobVO = findJobById(jobId);
		if(jobVO == null) {
			return;
		}
		jobDao.deleteJob(jobId);
		jobTrigger.deleteJob(jobVO);
	}
	
	/**
	 * 批量删除Job
	 * @param jobVOs
	 * @return
	 * @throws SchedulerException
	 */
	@PermissionOperation(code=PermissionOperation.DELETE, desc="iori.operation.deleteJob")
	@Transactional(transactionManager="txManager")
	@PostMapping(value="deleteJobs", produces = "application/json; charset=UTF-8")
	public int deleteJobs(@RequestBody List<JobVO> jobVOs) throws SchedulerException {
		for(JobVO jobVO : jobVOs) {
			deleteJob(jobVO.getJobId());
		}
		return 1;
	}
	
	/**
	 * 根据Group删除Job
	 * @param jobVO
	 * @return
	 * @throws SchedulerException 
	 */
	@PermissionOperation(code=PermissionOperation.DELETE, desc="iori.operation.deleteJob")
	@Transactional(transactionManager="txManager")
	@PostMapping(value="deleteJobByGroup", produces = "application/json; charset=UTF-8")
	public int deleteJobByGroup(@RequestBody JobVO jobVO) throws SchedulerException {
		List<JobVO> jobList =jobDao.findJobByGroup(jobVO);
		for(JobVO job : jobList) {
			jobTrigger.deleteJob(job);
		}
		jobDao.deleteJobByGroup(jobVO);
		return 1;
	}
	
	/**
	 * 更新Job信息
	 * @param jobVO
	 * @throws SchedulerException 
	 */
	@PermissionOperation(code=PermissionOperation.UPDATE, desc="iori.operation.editJob")
	@Transactional(transactionManager="txManager")
	@PutMapping(value="update", produces = "application/json; charset=UTF-8")
	public void updateJob(@RequestBody JobVO jobVO) throws SchedulerException {
		JobVO oldJobVO = findJobById(jobVO.getJobId());
		oldJobVO.setCron(jobVO.getCron());
		jobTrigger.rescheduleJob(oldJobVO);
		// 更新任务时，默认状态为运行中
		oldJobVO.setStatus(1);
		jobDao.updateJob(oldJobVO);
	}
	
	/**
	 * 批量更新Job
	 * @param jobVOs
	 * @return
	 * @throws SchedulerException
	 */
	@PermissionOperation(code=PermissionOperation.UPDATE, desc="iori.operation.editJob")
	@Transactional(transactionManager="txManager")
	@PostMapping(value="updateJobs", produces = "application/json; charset=UTF-8")
	public int updateJobs(@RequestBody List<JobVO> jobVOs) throws SchedulerException {
		for(JobVO jobVO : jobVOs) {
			try {
				updateJob(jobVO);
			} catch(SchedulerException e) {
				return -1;
			}
		}
		return 1;
	}
	
	/**
	 * 暂停任务
	 * @param jobId
	 * @throws SchedulerException
	 */
	@PermissionOperation(code="pause", desc="iori.operation.pauseJob")
	@Transactional(transactionManager="txManager")
	@PostMapping(value="pause/{jobId}", produces = "application/json; charset=UTF-8")
	public void pauseJob(@PathVariable("jobId")Integer jobId) {
		JobVO jobVO = findJobById(jobId);
		try {//特殊异常情况下会导致任务不能更新为暂停
			jobTrigger.pauseJob(jobVO);
		}catch(SchedulerException e) {}
		// 更新任务状态为暂停
		jobVO.setStatus(2);
		jobDao.updateJobStatus(jobVO);
	}
	
	/**
	 * 根据Group暂停Job
	 * @param jobVO
	 * @throws SchedulerException
	 */
	@PermissionOperation(code="pause", desc="iori.operation.pauseJob")
	@Transactional(transactionManager="txManager")
	@PostMapping(value="pauseJobByGroup", produces = "application/json; charset=UTF-8")
	public int pauseJobByGroup(@RequestBody JobVO jobVO) {
		List<JobVO> jobList = jobDao.findJobByGroup(jobVO);
		for(JobVO job : jobList) {
			try {//服务宕机未启动任务的情况不能抛出异常，外围系统会报错
				jobTrigger.pauseJob(job);
			} catch (SchedulerException e) {}
		}
		// 更新任务状态为暂停
		jobVO.setStatus(2);
		jobDao.updateJobStatusByGroup(jobVO);
		return 1;
	}
	
	/**
	 * 恢复任务
	 * @param jobId
	 * @throws SchedulerException
	 */
	@PermissionOperation(code="resume", desc="iori.operation.resumeJob")
	@Transactional(transactionManager="txManager")
	@PostMapping(value="resume/{jobId}", produces = "application/json; charset=UTF-8")
	public void resumeJob(@PathVariable("jobId")Integer jobId) throws SchedulerException {
		JobVO jobVO = findJobById(jobId);
		jobTrigger.resumeJob(jobVO);
		// 更新任务时，默认状态为运行中
		jobVO.setStatus(1);
		jobDao.updateJob(jobVO);
	}
	
	/**
	 * 立即运行任务
	 * @param jobId
	 * @throws SchedulerException
	 */
	@PermissionOperation(code="trigger", desc="iori.operation.triggerJob")
	@PostMapping(value="trigger/{jobId}", produces = "application/json; charset=UTF-8")
	public void triggerJob(@PathVariable("jobId")Integer jobId) throws SchedulerException {
		JobVO jobVO = findJobById(jobId);
		jobTrigger.triggerJob(jobVO);
	}
	

	/**
	 * 查询需要恢复的Job列表（过滤掉了失效状态的任务）
	 * @return
	 */
	public List<JobVO> findJobList4Resume() {
		return jobDao.findJobList4Resume();
	}
	
	/**
	 * 更新Job状态
	 * @param JobVO
	 */
	public void updateJobStatus(JobVO jobVO) {
		jobDao.updateJobStatus(jobVO);
	}

}
